package math;

public abstract class ExpressionBuilder {

  public static ArithmeticExpression add(ArithmeticExpression addend1, ArithmeticExpression addend2, ArithmeticExpression... addends) {
    ArithmeticExpression sum = Add.createAdd(addend1, addend2);
    for (int i = 0; i < addends.length; i++) {
      sum = Add.createAdd(sum, addends[i]);
    }
    return sum;
  }
  
  public static BooleanExpression and(BooleanExpression arg1, BooleanExpression arg2, BooleanExpression... args) {
    BooleanExpression and = And.createAnd(arg1, arg2);
    for (int i = 0; i < args.length; i++) {
      and = And.createAnd(and, args[i]);
    }
    return and;
  }

  public static BooleanExpression or(BooleanExpression arg1, BooleanExpression arg2, BooleanExpression... args) {
    BooleanExpression or = Or.createOr(arg1, arg2);
    for (int i = 0; i < args.length; i++) {
      or = Or.createOr(or, args[i]);
    }
    return or;
  }

  public static BooleanExpression xor(BooleanExpression arg1, BooleanExpression arg2, BooleanExpression... args) {
    BooleanExpression xor = Xor.createXor(arg1, arg2);
    for (int i = 0; i < args.length; i++) {
      xor = Xor.createXor(xor, args[i]);
    }
    return xor;
  }

  public static BooleanExpression beq(BooleanExpression arg1, BooleanExpression arg2, BooleanExpression... args) {
    BooleanExpression beq = BooleanEquality.createBooleanEquality(arg1, arg2);
    for (int i = 0; i < args.length; i++) {
      beq = BooleanEquality.createBooleanEquality(beq, args[i]);
    }
    return beq;
  }

  public static ArithmeticExpression mult(ArithmeticExpression factor1, ArithmeticExpression factor2, ArithmeticExpression... factors) {
    ArithmeticExpression product = Mult.createMult(factor1, factor2);
    for (int i = 0; i < factors.length; i++) {
      product = Mult.createMult(product, factors[i]);
    }
    return product;
  }
  
  public static ArithmeticExpression div(ArithmeticExpression numerator, ArithmeticExpression denominator){
    return mult(numerator, pow(denominator, IntegerConstant.MINUS_ONE));
  }
  
  public static ArithmeticExpression pow(ArithmeticExpression base, ArithmeticExpression exponent){
    return Pow.createPow(base, exponent);
  }
  
  public static ArithmeticExpression sub(ArithmeticExpression minuend, ArithmeticExpression subtrahend){
    return add(minuend, neg(subtrahend));
  }
  
  public static ArithmeticExpression neg(ArithmeticExpression arg){
    return Negation.createNegation(arg);
  }

  public static BooleanExpression not(BooleanExpression arg){
    return Not.createNot(arg);
  }

  public static ArithmeticExpression sin(ArithmeticExpression arg){
    return Sin.createSin(arg);
  }
  
  public static ArithmeticExpression cos(ArithmeticExpression arg){
    return Cos.createCos(arg);
  }
  
  public static ArithmeticExpression tan(ArithmeticExpression arg){
    return div(sin(arg), cos(arg));
  }

  public static ArithmeticExpression exp(ArithmeticExpression arg){
    return Exp.createExp(arg);
  }

  public static ArithmeticExpression ln(ArithmeticExpression arg){
    return Ln.createLn(arg);
  }
}
